package com.graduate.utils;

import com.graduate.exception.BizException;
import com.graduate.exception.ExceptionEnum;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.Resource;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;

@Slf4j
public class FileUtils {

    protected Logger logger = LoggerFactory.getLogger(this.getClass());

    public static String getPrefix(String name) {
        return name.substring(0, name.lastIndexOf("."));
    }

    public static String getSuffixWithoutDot(String name) {
        return name.substring(name.lastIndexOf(".") + 1);
    }
    public static String getSuffixWithDot(String name) {
        return name.substring(name.lastIndexOf("."));
    }
    // Android端下载Apk文件不使用此方法，详情见 AppUpdateController.java 中的下载方法 与 解释
    // Web端使用此方法
    // 实现Spring Boot 的文件下载功能
    public static boolean downloadFile(Resource resource, HttpServletResponse response) throws IOException {
        String fileName = resource.getFilename();
        File file = resource.getFile();
        // 如果文件名存在，则进行下载
        if (file.exists()) {
            response.setContentType("application/force-download");// 设置强制下载不打开
            response.addHeader("Content-Disposition", "attachment;fileName=" + fileName);// 设置文件名
            byte[] buffer = new byte[1024];
            FileInputStream fis = null;
            BufferedInputStream bis = null;
            try {
                fis = new FileInputStream(file);
                bis = new BufferedInputStream(fis);
                OutputStream os = response.getOutputStream();
                int i = bis.read(buffer);
                while (i != -1) {
                    os.write(buffer, 0, i);
                    i = bis.read(buffer);
                }
                return true;
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                if (bis != null) {
                    try {
                        bis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
                if (fis != null) {
                    try {
                        fis.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
        return false;
    }

    public static String saveImageToLocal(MultipartFile file, String fileUploadPath) {
        if (file == null) {
            throw new BizException(ExceptionEnum.BODY_NOT_MATCH);
        }
        // file先进行非空判断，才能调用getOriginalFilename函数，避免空指针错误
        String filename = file.getOriginalFilename();
        //assert断言：用于调试，一定程度替换System.out/if等来输出调试信息
        assert filename != null : "filename为空值，抛出AssertionError";
        if (!filename.endsWith(".jpg")
                && !filename.endsWith(".png")
                && !filename.endsWith(".jpeg")
                && !filename.endsWith(".gif")) {
            throw new BizException(ExceptionEnum.BODY_NOT_MATCH);
        } else {
            // 获取文件前、后缀
            String prefixName = filename.substring(0, filename.lastIndexOf("."));
            String suffixName = filename.substring(filename.lastIndexOf("."));
            // 生成新的文件名称，避免多次提交相同文件导致服务器中文件名冲突
            StringBuilder sb = new StringBuilder();
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmssSSS");
            String newFileName = sb.append(prefixName)
                    .append("_")
                    .append(simpleDateFormat.format(new Date()))
                    .append(suffixName)
                    .toString();
            try {
                // 保存文件到本地文件夹
                byte[] bytes = file.getBytes();
                Path path = Paths.get(fileUploadPath + newFileName);
                Files.write(path, bytes);
            } catch (IOException e) {
                e.printStackTrace();
                return "";
            }
            return newFileName;
        }
    }

    public static String generateNewFileName(String oldFileName) {
        //assert断言：用于调试，一定程度替换System.out/if等来输出调试信息
        assert oldFileName != null : "filename为空值，抛出AssertionError";
        if (!oldFileName.endsWith(".jpg")
                && !oldFileName.endsWith(".png")
                && !oldFileName.endsWith(".jpeg")
                && !oldFileName.endsWith(".gif")) {
//            throw new BusinessException(BaseResponseCode.IMAGE_TYPE_ERROR);
            throw new BizException(ExceptionEnum.BODY_NOT_MATCH);
        } else {
            // 获取文件前、后缀
            String prefixName = oldFileName.substring(0, oldFileName.lastIndexOf("."));
            String suffixName = oldFileName.substring(oldFileName.lastIndexOf("."));
            // 生成新的文件名称，避免多次提交相同文件导致服务器中文件名冲突
            StringBuilder sb = new StringBuilder();
            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyyMMddHHmmssSSS");
            String newFileName = sb.append(prefixName)
                    .append("_")
                    .append(simpleDateFormat.format(new Date()))
                    .append(suffixName)
                    .toString();
            return newFileName;
        }
    }

    public static String file2Base64(File file) {
        if (file == null) {
            return null;
        }
        String base64 = null;
        FileInputStream fin = null;
        try {
            fin = new FileInputStream(file);
            byte[] buff = new byte[fin.available()];
            fin.read(buff);
            base64 = Base64.getEncoder().encodeToString(buff);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fin != null) {
                try {
                    fin.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return base64;
    }

    public static File base64ToFile(String base64, File file) {
        if (base64 == null || "".equals(base64)) {
            return null;
        }
        byte[] buff = Base64.getDecoder().decode(base64);
        FileOutputStream fout = null;
        try {
            // Base64转为本地临时文件,如果目录不存在就创建
            if (!file.exists()) {
//                boolean res = file.mkdir();
                try {
                    file.createNewFile();
                    System.out.println("创建文件成功了");
                } catch (IOException e) {
                    e.printStackTrace();
                    System.out.println("创建文件失败了");
                    return null;
                }
                /*if (res) {
                    System.out.println("目录不存在，创建成功");
                } else {
                    System.out.println("目录不存在，创建失败");
                    return null;
                }*/
            }
            fout = new FileOutputStream(file);
            fout.write(buff);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fout != null) {
                try {
                    fout.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return file;
    }
    public static File writeByteArrayToFile( File file,byte[] Bytes) {
        if (Bytes == null || "".equals(Bytes)) {
            return null;
        }
        FileOutputStream fout = null;
        try {
            // Base64转为本地临时文件,如果目录不存在就创建
            if (!file.exists()) {
                boolean res = file.mkdir();
                if (res) {
                    System.out.println("目录不存在，创建成功");
                } else {
                    System.out.println("目录不存在，创建失败");
                    return null;
                }
            }
            fout = new FileOutputStream(file);
            fout.write(Bytes);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fout != null) {
                try {
                    fout.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return file;
    }
    public static File base64ToFile(String base64, String tmpPath) {
        if (base64 == null || "".equals(base64)) {
            return null;
        }
        byte[] buff = Base64.getDecoder().decode(base64);
        File file = null;
        FileOutputStream fout = null;
        try {
            // Base64转为本地临时文件,如果目录不存在就创建
            file = new File(tmpPath.substring(0, tmpPath.lastIndexOf("/")));
            if (!file.exists()) {
                boolean res = file.mkdir();
                if (res) {
                    System.out.println("目录不存在，创建成功");
                } else {
                    System.out.println("目录不存在，创建失败");
                    return null;
                }
            }
            file = new File(tmpPath);
            fout = new FileOutputStream(file);
            fout.write(buff);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (fout != null) {
                try {
                    fout.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return file;
    }

    public static InputStream file2InputStream(File file) throws FileNotFoundException {
        return new FileInputStream(file);
    }

    /** 删除文件
     *
     * @param file
     * @return
     */
    public static boolean deleteFile(File file) {
        if (file.exists() && file.isFile()) {
            return file.delete();
        } else {
            return false;
        }
    }





    public /*static*/ void main(String[] args) throws Exception {
        String fileStr = getFileStr("/Users/zhaobo/Downloads/workpro/healthcommission/src/com//*static*//q.pdf");
        System.out.println("fileStr ===" + fileStr);
        System.out.println(generateFile(fileStr, "/Users/zhaobo/Downloads/workpro/healthcommission/src/com//*static*//w.pdf"));
        System.out.println("end");
        String file = "/Users/zhaobo/Downloads/workpro/healthcommission/src/com//*static*//q.pdf";
        System.out.println(getFileName(file));
        System.out.println(getFileExtension(file));
        System.out.println(getFileNameAll(file));
        System.out.println(getFilePath(file));

    }


    /**
     * 文件转化成base64字符串
     * 将文件转化为字节数组字符串，并对其进行Base64编码处理
     *
     * @param filePath 文件路径
     * @return base字符串
     */
    public /*static*/ String getFileStr(String filePath) {
        InputStream in = null;
        byte[] data = null;
        // 读取文件字节数组
        try {
            in = new FileInputStream(filePath);
            data = new byte[in.available()];
            in.read(data);
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        // 对字节数组Base64编码
        BASE64Encoder encoder = new BASE64Encoder();
        // 返回 Base64 编码过的字节数组字符串
        return encoder.encode(data);
    }


    /**
     * base64字符串转化成文件，可以是JPEG、PNG、TXT和AVI等等
     *
     * @param base64FileStr base64字符串
     * @param filePath      转换后文件名-包含路径
     * @return
     * @throws Exception
     */
    public /*static*/ boolean generateFile(String base64FileStr, String filePath) throws Exception {
        // 数据为空
        if (base64FileStr == null) {
            System.out.println(" 不行，oops！ ");
            return false;
        }
        BASE64Decoder decoder = new BASE64Decoder();


        // Base64解码,对字节数组字符串进行Base64解码并生成文件
        byte[] byt = decoder.decodeBuffer(base64FileStr);
        for (int i = 0, len = byt.length; i < len; ++i) {
            // 调整异常数据
            if (byt[i] < 0) {
                byt[i] += 256;
            }
        }
        OutputStream out = null;
        InputStream input = new ByteArrayInputStream(byt);
        try {
            // 生成指定格式的文件
            out = new FileOutputStream(filePath);
            byte[] buff = new byte[1024];
            int len = 0;
            while ((len = input.read(buff)) != -1) {
                out.write(buff, 0, len);
            }
        } catch (IOException e) {
            logger.error("------------------->INFO:  该文件路径bu存在「" + filePath + "」");
        } finally {
            out.flush();
            out.close();
        }
        return true;
    }

    /** 获取文件名称(不包含路径)
     * @param filePath
     * @return
     */
    public /*static*/ String getFileName(String filePath) {
        return filePath.substring(filePath.lastIndexOf("/")+1, filePath.lastIndexOf("."));
    }

    /**
     * 获取文件后缀名（包含.）
     * @param filePath
     * @return
     */
    public /*static*/ String getFileExtension(String filePath) {
        return filePath.substring(filePath.lastIndexOf("."));
    }

    /**
     * 获取文件名称（包含后缀名）
     * @param filePath
     * @return
     */
    public /*static*/ String getFileNameAll(String filePath) {
        return filePath.substring(filePath.lastIndexOf("/")+1);
    }

    /**
     * 获取文件路径
     * @param filePath
     * @return
     */
    public /*static*/ String getFilePath(String filePath) {
        return filePath.substring(0, filePath.lastIndexOf("/"));
    }



}
